Whonix friendly applications best practices
Best practices on writing applications compatible with Whonix.
config.d support[edit]
Please parse a configuration directory to apply options to your application, such as parsing /etc/your-application.d
configuration folder (and /usr/local/etc/your-application.d
for better Qubes support) so Linux distributions such as Debian, Kicksecure™ and Whonix can set defaults (such as proxy / stream isolation configuration). Users are of course free to overrule these defaults using the usual configuration files in the user's home folder.
Please parse only configuration files with a defined file extension such as .conf
to avoid parsing backup, swap and temporary files. Graphical editors such as kate
create backup files such as file-name~
, vim create .file-name.swp
or APT / dpkg creating files such as file-name.dpkg-old
which would lead to unexpected results, should be ignored by your parsing logic.
The parsing rules should be consistent and documented, preferably on the manual page or the program's documentation. As of Tor version 4.7.10, the manual page describes the parsing logic and could inspire the parsing design of your application:
Configuration options can be imported from files or folders using the %include option with the value being a path. This path can have wildcards. Wildcards are expanded first, then sorted using lexical order. Then, for each matching file or folder, the following rules are followed: if the path is a file, the options from the file will be parsed as if they were written where the %include option is. If the path is a folder, all files on that folder will be parsed following lexical order. Files starting with a dot are ignored. Files in subfolders are ignored. The %include option can be used recursively. New configuration files or directories cannot be added to already running Tor instance if Sandbox is enabled.
It is important the parsing occurs has a defined order, such as the lexical.
If it is lexical, the configuration shipped with your program named 00_default.conf
for example, has a lower precedence compared to an anonymity system configuration file that overrides the default options with a file parsed later 30_whonix.conf
. A user can then overwrite all configuration files by making it be last one to be parse, named 50_user.conf
as an example.
It is also possible to combine the lexical order with overriding by last match, stopping on the first match. It is up to your team to design what is best for the development of the program, as long as it is documented clearly, you are taking the first step for your application to become Tor friendly.
Stream Isolation[edit]
Please set SOCKS user name for Stream Isolation, this enables IsolateSOCKSAuth which is one of the default isolation flags for tor ports used by clients. This method enforces stream isolation on the application level independent of other applications using the same port, different SOCKS Authorizations will be stream isolated.
Ephemeral onion services[edit]
- Please use
ADD_ONION
Tor control protocol command / Tor ephemeral onion services.
ephemeral: Means the onion service will be gone after the Tor control connection is closed. It's however possible to retrieve onion service private key and to restore it at next run. It is important for your application to retry ADD_ONION
after the Tor control connection is closed so the user does not have to stop and start your application again to retrieve an onion service. If your application uses Flags=Detach
, it is important for your program to issue the DEL_ONION
controller command to avoid having an onion hanging when your application has already closed.
Tor ephemeral onion services are a lot a lot better for Whonix than preconfigued Tor hidden services because it does not require the user to configure onion services manually, therefore a better usability.
OnionShare by @micahflee has superb Tails and Whonix support. (See also Whonix's OnionShare user documentation.)
Listening Interface[edit]
The listening interface is that interface that your program will bind to listen for incoming connections.
- Listen on all interfaces (0.0.0.0) rather than just 127.0.0.1. (This is required since the incoming onion service connection comes from the network, not from localhost.)
# In Whonix, listen on 0.0.0.0 instead of 127.0.0.1 if os.path.exists('/usr/share/anon-ws-base-files/workstation'): host = '0.0.0.0' else: host = '127.0.0.1'
Related: Listen Port Convention
Listening Port[edit]
- Don't listen on a random local server port, instead listen on a specific local server port or port range. Using this method, it is easier to open only the necessary range of incoming ports on the firewall instead of all ports, as it would not be possible to automate the process of opening the firewall port when there is no range.
- Tor
VIRTPROT
(remote virtual port on the onion service) does not matter.
An application that applies that listening port methodology is Onionshare:
- OnionShare uses
17600 - 17659
. That is handy, so we can match for it using(176[0-5][0-9])
in the onionshare onion-grater whitelist config. - That way OnionShare (running inside a compromised Workstation) cannot open arbitrary ports on the workstation. For example, not to the real Tor
ControlPort
and circumvent the filtering. (We use TorControlSocket
rather thanControlPort
now for this reason.) There are no local ports open on Whonix-Gateway™ besides TorSocks
,DNS
andTransPort
, but if there was (let's say for example for brltty), then we don't want connections to it. - That allows us to set a limit on how many Tor hidden services (a compromised) workstation can create.
- It's also useful so users don't have to open all incoming ports in Whonix-Workstation Firewall.
Tor Settings Autodetection[edit]
- Auto detect Tor settings through
TOR_*
environment variables.
In Whonix:
TOR_CONTROL_IPC_PATH=/var/run/anon-ws-disable-stacked-tor/127.0.0.1_9151.sock
TOR_SOCKS_IPC_PATH=/var/run/anon-ws-disable-stacked-tor/127.0.0.1_9150.sock
These are Unix domain socket files.
Ports works fine for Whonix as per design the Workstation is isolated and uses the Gateway as its only source of networking, but nowadays Unix domain socket files are much more advisable since these are less likely to leak for non-isolated systems.
Robustness[edit]
- The application should not crash if Tor
ControlPort
replies something unexpected such as510 Command filtered
.
If the application does crash, even though it can not get replies from the tor controller by receiving 510 Command filtered
, the user won't understand why your program is not working and won't try to use it again, that is not a good user experience. The application should have error handling for unexpected tor control replies.
Usability[edit]
- Show an error message if Whonix is detected and
ControlPort
receiving510 Command filtered
replies. Sample error message:Error talking to the Tor controller, command sent: 'XXX', received reply: 'YYY'. If you're using Whonix, check out https://www.whonix.org/wiki/ProgramName to make ProgramName work.
- onionshare has a Tor settings dialog. But not really needed in Whonix.
Bonus[edit]
Connections to the controller are passed through a proxy called onion-grater, which only allows basic features by default. After the profile is built for your program, your application should work gracefully.
- Bonus: Make a list of Tor control commands you are using so an onion-grater profile can be written.
- Bonus: Write an onion-grater profile.
Programmatically Detecting Whonix[edit]
Various marker files are available:
- Whonix generally:
/usr/share/whonix/marker
- Whonix-Gateway:
/usr/share/anon-gw-base-files/gateway
- Whonix-Workstation™:
/usr/share/anon-ws-base-files/workstation
See Also[edit]
Forum Discussion[edit]
https://forums.whonix.org/t/whonix-friendly-applications-best-practices
We believe security software like Whonix needs to remain open source and independent. Would you help sustain and grow the project? Learn more about our 12 year success story and maybe DONATE!